package cn.xttc.edu.util.sms;

import cn.xttc.edu.entity.sms.SendResponse;
import cn.xttc.edu.entity.sms.VerifyResponse;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * 短信验证码工具类
 * @author yl
 */
public class SendSMSUtils {
    private static final String URI_SEND_SMS = "https://sms.dun.163.com/v2/sendsms";
    private static final String URI_VERIFY_OTP = "https://sms.dun.163.com/v2/verifysms";

    /**
     * SECRET_ID 和 SECRET_KEY 是产品密钥。
     */
    private static final String SECRET_ID = "52c9e8f56ebd29d673799969adf4b30c";
    private static final String SECRET_KEY = "c5bb73101742d71f87b7d30f471789e1";

    private SendSMSUtils () {}

    /**
     * 发送验证码短信：指明由易盾生成验证码
     * @param phone 接收方手机号
     */
    public static SendResponse sendOtp(String phone) {
        // 这是你的 国内验证码短信 业务的 ID。可以登录易盾官网查看此业务 ID。
        String businessId = "7736a8f77362442d87527b32cffd2672";
        // 这是你事先创建好的模板，且已通过审核。
        String templateId = "16309";

        // 此处假设目标模板内容里只有验证码一个变量，所以没有其它变量需要指定
        Map<String, String> variables = Collections.emptyMap();

        // 发国内短信时，不指定 Country Calling Code
        Map<String, String> param = createSendParam(businessId, templateId, variables, phone);

        return RequestUtils.postForEntity(URI_SEND_SMS, param, SendResponse.class);
    }

    /**
     * 验证用户回填的验证码
     *
     * @param requestId 之前发送验证码短信时，易盾返回的请求 ID。
     * @param code      用户回填的验证码。
     */
    public static VerifyResponse verifyOtp(String requestId, String code) {
        // 业务 ID。与前述发短信时所用的业务 ID 相同。
        String businessId = "7736a8f77362442d87527b32cffd2672";

        Map<String, String> param = createVerifyParam(businessId, requestId, code);

        return RequestUtils.postForEntity(URI_VERIFY_OTP, param, VerifyResponse.class);
    }

    /**
     * 构建发送验证码短信的请求参数：指明由易盾生成验证码
     */
    private static Map<String, String> createSendParam(
            String businessId, String templateId, Map<String, String> variables, String to) {
        Map<String, String> params = new HashMap<>();

        params.put("nonce", ParamUtils.createNonce());
        params.put("timestamp", String.valueOf(System.currentTimeMillis()));
        params.put("version", "v2");

        params.put("secretId", SECRET_ID);
        params.put("businessId", businessId);

        params.put("templateId", templateId);
        params.put("mobile", to);

        params.put("paramType", "json");
        params.put("params", ParamUtils.serializeVariables(variables));

        // 指明由易盾生成验证码：
        //codeName 表示目标模板内容中，验证码的占位符变量名。如，模板内容为 “您的验证码为 ${code}，5 分钟内有效，请勿泄露。”，则 codeName 的值应为 code
        params.put("codeName", "code");
        //codeLen 表示验证码的数字个数
        params.put("codeLen", "6");
        //codeValidSec 表示验证码的有效期。单位：秒
        params.put("codeValidSec", "300");

        // 在最后一步生成此次请求的签名
        params.put("signature", ParamUtils.genSignature(SECRET_KEY, params));

        return params;
    }

    /**
     * 构建验证码校验请求的参数
     */
    private static Map<String, String> createVerifyParam(String businessId, String requestId, String code) {
        Map<String, String> params = new HashMap<>();

        params.put("nonce", ParamUtils.createNonce());
        params.put("timestamp", String.valueOf(System.currentTimeMillis()));
        params.put("version", "v2");

        params.put("secretId", SECRET_ID);
        params.put("businessId", businessId);

        params.put("requestId", requestId);
        params.put("code", code);

        // 在最后一步生成此次请求的签名
        params.put("signature", ParamUtils.genSignature(SECRET_KEY, params));

        return params;
    }
}
